package cloud.demarcia.rabbitregister.service.impl;

import cloud.demarcia.rabbitregister.constant.RedisConstant;
import cloud.demarcia.rabbitregister.entity.MemberEntity;
import cloud.demarcia.rabbitregister.enums.RegisterStatusCode;
import cloud.demarcia.rabbitregister.exception.RabbitRegisterException;
import cloud.demarcia.rabbitregister.repository.MemberRepository;
import cloud.demarcia.rabbitregister.service.MailService;
import cloud.demarcia.rabbitregister.service.RegisterService;
import cloud.demarcia.rabbitregister.util.PasswordEncipher;
import cloud.demarcia.rabbitregister.vo.UserRegisterVo;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author Bojun Wen, wen_bj@outlook.com
 * @date 2022.02.09
 */
@Service
@Slf4j
public class RegisterServiceImpl implements RegisterService {
    @Resource
    private StringRedisTemplate template;
    @Resource
    private MemberRepository memberRepository;
    @Resource
    private MailService mailService;
    @Resource
    private PasswordEncipher passwordEncipher;
    private final String SMS_CODE_CACHE_PREFIX= RedisConstant.REGISTER_EMAIL_PREFIX;

    @Override
    public void register(UserRegisterVo userRegisterVo) {
        if(!matchCode(userRegisterVo.getEmail(), userRegisterVo.getCode())) {
            throw new RabbitRegisterException(RegisterStatusCode.CODE_ERROR);
        }
        int count = memberRepository.countByEmail(userRegisterVo.getEmail());
        if(count>0) throw new RabbitRegisterException(RegisterStatusCode.ALREADY_REGISTERED);
        mailService.sendRegisterSuccessMail(userRegisterVo.getEmail(), userRegisterVo.getUsername());
        MemberEntity entity=new MemberEntity();
        entity.setEmail(userRegisterVo.getEmail());
        entity.setUsername(userRegisterVo.getUsername());
        entity.setPassword(passwordEncipher.encode(userRegisterVo.getPassword()));
        memberRepository.save(entity);
        count = memberRepository.countByEmail(userRegisterVo.getEmail());
        if(count==0) throw new RabbitRegisterException(RegisterStatusCode.SYSTEM_ERROR);
    }

    @Override
    public void sendVerificationCode(String email) {
        log.info("收到的的邮件地址是{}",email);
        //验证邮件地址是否合法
        boolean match = ReUtil.isMatch("^[a-z]([a-z0-9]*[-_]?[a-z0-9]+)*@([a-z0-9]*[-_]?[a-z0-9]+)+[\\.][a-z]{2,3}([\\.][a-z]{2})?$", email);
        if(!match) throw new RabbitRegisterException(RegisterStatusCode.EMAIL_INVALID);
        //查询数据库当前邮件地址是否已注册
        int count = memberRepository.countByEmail(email);
        if(count>0) throw new RabbitRegisterException(RegisterStatusCode.ALREADY_REGISTERED);
        //发送邮件验证码
        String code=generateCode(email);
        mailService.sendRegisterCodeMail(email,code);
    }

    private String generateCode(String email){
        //接口防刷
        String cachedCode=template.opsForValue().get(SMS_CODE_CACHE_PREFIX+email);
        if (!StrUtil.isEmpty(cachedCode)) {
            throw new RabbitRegisterException(RegisterStatusCode.TOO_FREQUENT);
        }
        int code = (int) ((Math.random() * 9 + 1) * 100000);
        String codeNum = String.valueOf(code);
        template.opsForValue().set(SMS_CODE_CACHE_PREFIX+email,codeNum,2, TimeUnit.MINUTES);
        return codeNum;
    }

    private boolean matchCode(String email,String code){
        String cachedCode=template.opsForValue().get(SMS_CODE_CACHE_PREFIX+email);
        if (StrUtil.isEmpty(cachedCode)) {
            return false;
        }
        return code.equals(cachedCode);
    }


}
